package org.etherframework.tests.features.access
{
	import flash.system.ApplicationDomain;
	
	import mx.core.IVisualElement;
	
	import org.etherframework.tests.features.access.configs.GlobalConfig;
	import org.etherframework.tests.features.access.mediators.ChildMediator;
	import org.etherframework.tests.features.access.mediators.GlobalMediator;
	import org.etherframework.tests.features.access.mediators.Module2Mediator;
	import org.etherframework.tests.features.access.mediators.ModuleMediator;
	import org.etherframework.tests.features.access.mediators.OverlapedMediator;
	import org.etherframework.tests.features.access.mediators.TopMediator;
	import org.etherframework.tests.features.access.views.ChildMediatorView;
	import org.etherframework.tests.features.access.views.GlobalMediatorView;
	import org.etherframework.tests.features.access.views.Module2MediatorView;
	import org.etherframework.tests.features.access.views.ModuleMediatorView;
	import org.etherframework.tests.features.access.views.OverlapedMediatorView;
	import org.etherframework.tests.features.access.views.TopMediatorView;
	import org.etherframework.tests.utils.ModuleInfo;
	import org.etherframework.tests.utils.TestUtility;
	import org.fluint.uiImpersonation.UIImpersonator;
	import org.hamcrest.assertThat;
	import org.hamcrest.object.instanceOf;
	import org.hamcrest.object.notNullValue;
	
	import spark.components.Group;

	public class when_using_mediator_hierarchical_access
	{	
		private static var _testUtility:TestUtility = new TestUtility();
		private static var _globalView:Group;
		
		private static var _topModule:ModuleInfo;
		private static var _module:ModuleInfo;
		private static var _childModule:ModuleInfo;
		private static var _module2:ModuleInfo;
		private static var _globalModule:ModuleInfo;
		
		[BeforeClass]
		public static function setUpBeforeClass():void
		{
			const appDomain:ApplicationDomain = ApplicationDomain.currentDomain;
			_topModule = _testUtility.createModuleInfo(null, null, null, null, appDomain);
			_module = _testUtility.createModuleInfo(null, null, null, null, appDomain);
			_childModule = _testUtility.createModuleInfo(null, null, null, null, appDomain);
			_module2 = _testUtility.createModuleInfo(null, null, null, null, appDomain);
			_globalModule = _testUtility.createModuleInfo(new GlobalConfig(), null, null, null, appDomain);
			_globalView = UIImpersonator.addChild(new Group()) as Group;
			
			// Module hierarchical structure is view dependent. So as to resolve ancestor
			// module you need to address some ancestor view which hosts other module.
			_globalView.addElement(_topModule.module.view as IVisualElement);
			Group(_topModule.module.view).addElement(_module.module.view as IVisualElement);
			Group(_topModule.module.view).addElement(_module2.module.view as IVisualElement);
			Group(_module.module.view).addElement(_childModule.module.view as IVisualElement);
			
			_topModule.module.mediators.addMediator(TopMediatorView, TopMediator);
			_topModule.module.mediators.addMediator(OverlapedMediatorView, OverlapedMediator);
			_module.module.mediators.addMediator(ModuleMediatorView, ModuleMediator);
			_module.module.mediators.addMediator(OverlapedMediatorView, OverlapedMediator);
			_module2.module.mediators.addMediator(Module2MediatorView, Module2Mediator);
			_childModule.module.mediators.addMediator(ChildMediatorView, ChildMediator);
			_globalModule.module.mediators.addMediator(GlobalMediatorView, GlobalMediator);
		}
		
		[AfterClass]
		public static function tearDownAfterClass():void
		{
			_testUtility.dispose();
		}
		
		[Test(order=1)]
		public function when_getting_top_mediator_it_should_be_resolved():void
		{
			var error:Error;
			try {
				_topModule.module.ether.mediators.createMediator(new GlobalMediatorView())
			} catch (e:Error) {error = e;}
			assertThat(error, notNullValue());
			
			assertThat(_topModule.module.ether.mediators.createMediator(new TopMediatorView()), instanceOf(TopMediator));
			assertThat(_module.module.ether.mediators.createMediator(new TopMediatorView()), instanceOf(TopMediator));
			assertThat(_childModule.module.ether.mediators.createMediator(new TopMediatorView()), instanceOf(TopMediator));
		}
		
		[Test(order=2)]
		public function when_getting_module_mediator_it_should_be_resolved():void
		{
			var error:Error;
			
			try {
				_module.module.ether.mediators.createMediator(new GlobalMediatorView())
			} catch (e:Error) {error = e;}
			assertThat(error, notNullValue());
			error = null;
			
			try {
				_topModule.module.ether.mediators.createMediator(new ModuleMediatorView())
			} catch (e:Error) {error = e;}
			assertThat(error, notNullValue());
			
			assertThat(_module.module.ether.mediators.createMediator(new ModuleMediatorView()), instanceOf(ModuleMediator));
			assertThat(_childModule.module.ether.mediators.createMediator(new ModuleMediatorView()), instanceOf(ModuleMediator));
		}
		
		[Test(order=3)]
		public function when_getting_child_mediator_it_should_be_resolved():void
		{
			var error:Error;
			
			try {
				_childModule.module.ether.mediators.createMediator(new GlobalMediatorView())
			} catch (e:Error) {error = e;}
			assertThat(error, notNullValue());
			error = null;
			
			try {
				_topModule.module.ether.mediators.createMediator(new ChildMediatorView())
			} catch (e:Error) {error = e;}
			assertThat(error, notNullValue());
			error = null;
			
			try {
				_module.module.ether.mediators.createMediator(new ChildMediatorView())
			} catch (e:Error) {error = e;}
			assertThat(error, notNullValue());
			
			assertThat(_childModule.module.ether.mediators.createMediator(new ChildMediatorView()), instanceOf(ChildMediator));
		}
		
		[Test(order=4)]
		public function when_getting_dependencies_from_another_branch_it_should_be_resolved():void
		{
			var error:Error;
			
			assertThat(_module2.module.ether.mediators.createMediator(new TopMediatorView()), instanceOf(TopMediator));
			assertThat(_module2.module.ether.mediators.createMediator(new Module2MediatorView()), instanceOf(Module2Mediator));
			
			try {
				_module2.module.ether.mediators.createMediator(new GlobalMediatorView())
			} catch (e:Error) {error = e;}
			assertThat(error, notNullValue());
			error = null;
			
			try {
				_module2.module.ether.mediators.createMediator(new ModuleMediatorView())
			} catch (e:Error) {error = e;}
			assertThat(error, notNullValue());
		}
	}
}